package recolhalixo;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.Stack;

import jadex.bdi.runtime.IMessageEvent;
import jadex.bdi.runtime.Plan;
import jadex.bdi.runtime.Plan.SyncResultListener;
import jadex.bridge.IComponentIdentifier;
import jadex.bridge.fipa.SFipa;
import jadex.bridge.service.types.cms.CMSComponentDescription;
import jadex.extension.envsupport.environment.ISpaceAction;
import jadex.extension.envsupport.environment.ISpaceObject;
import jadex.extension.envsupport.environment.space2d.Grid2D;
import jadex.extension.envsupport.environment.space2d.Space2D;
import jadex.extension.envsupport.math.IVector1;
import jadex.extension.envsupport.math.IVector2;
import jadex.extension.envsupport.math.Vector1Int;
import jadex.extension.envsupport.math.Vector2Int;

public class PlanoRecolherLixo extends Plan {
	
	private LinkedList<IVector2> bestPath; // caminho a seguir

	@Override
	public void body() {
		Grid2D env = (Grid2D)getBeliefbase().getBelief("env").getFact();
		IVector2 myPos = (IVector2)env.getSpaceObject(env.getAvatar(getComponentDescription()).getId()).getProperty(Space2D.PROPERTY_POSITION);
		BaseConhecimento bc = (BaseConhecimento)getBeliefbase().getBelief("knows").getFact();
		bc.setTick((long)getClock().getTick());
		getBeliefbase().getBelief("knows").setFact(bc);
		String tipoCamiao=(String)env.getSpaceObject(env.getAvatar(getComponentDescription()).getId()).getProperty("type");
		ArrayList<IVector2> objectivos=new ArrayList<IVector2>();
		for (IVector2 c:bc.getGoals((int)getClock().getTick())) {
			int px=c.getXAsInteger();
			int py=c.getYAsInteger();
			
			Vector2Int pcima=new Vector2Int(px,py-1);
			Vector2Int pbaixo=new Vector2Int(px,py+1);
			Vector2Int pesquerda=new Vector2Int(px-1,py);
			Vector2Int pdireita=new Vector2Int(px+1,py);
			
			if (env.getSpaceObjectsByGridPosition(pcima, "estrada") != null) {
				objectivos.add(pcima);
			}
			if (env.getSpaceObjectsByGridPosition(pbaixo, "estrada") != null) {
				objectivos.add(pbaixo);
			}
			if (env.getSpaceObjectsByGridPosition(pesquerda, "estrada") != null) {
				objectivos.add(pesquerda);
			}
			if (env.getSpaceObjectsByGridPosition(pdireita, "estrada") != null) {
				objectivos.add(pdireita);
			}
		}
		
		if (!objectivos.isEmpty()) {
			bestPath=PathFinder.findPath(myPos,objectivos, env);
			
			// MOVE
			if (bestPath.size()>1) {
				Map params = new HashMap();
				bestPath.pop();
				IVector2 nextPos=bestPath.getFirst();
				int npx=nextPos.getXAsInteger();
				int npy=nextPos.getYAsInteger();
				int mpx=myPos.getXAsInteger();
				int mpy=myPos.getYAsInteger();
				
				if (npy<mpy) {params.put(AccaoMover.DIRECCAO, AccaoMover.CIMA);}
				else if (npy>mpy) {params.put(AccaoMover.DIRECCAO, AccaoMover.BAIXO);}
				else if (npx<mpx) {params.put(AccaoMover.DIRECCAO, AccaoMover.ESQUERDA);}
				else if (npx>mpx) {params.put(AccaoMover.DIRECCAO, AccaoMover.DIREITA);}
				
				params.put(ISpaceAction.OBJECT_ID, env.getAvatar(getComponentDescription()).getId());
				params.put("quantity", getBeliefbase().getBelief("quantity").getFact());
				SyncResultListener srl	= new SyncResultListener();
				env.performSpaceAction("mover", params, srl); 
				srl.waitForResult();
			}
			else {
				// MENSAGEM ANTES
				Broadcaster.broadcastGarbage(this);
				
				// Pára algum tempo
				try {Thread.sleep(250);} catch (InterruptedException e) {}
				
				Integer oldQtd=(Integer)this.getBeliefbase().getBelief("quantity").getFact();
				Integer cap=(Integer)this.getBeliefbase().getBelief("capacity").getFact();
				Map params = new HashMap();
				params.put(ISpaceAction.OBJECT_ID, env.getAvatar(getComponentDescription()).getId());
				params.put("quantity", oldQtd);
				params.put("capacity", cap);
				SyncResultListener srl	= new SyncResultListener();
				env.performSpaceAction("recolher", params, srl);
				Integer recolhido=(Integer)srl.waitForResult();
				this.getBeliefbase().getBelief("quantity").setFact(oldQtd+recolhido);
				// MENSAGEM DEPOIS
				Broadcaster.broadcastGarbage(this);
			}
		}
	}
	
}
